package cn.zn.framework.common.utils;

import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;

public class ImageUtil {
    /**
     * 图片水印
     *
     * @param watermarkImg 水印图片
     * @param targetImg    目标图片
     * @param x            修正值 默认在中间
     * @param y            修正值 默认在中间
     * @param alpha        透明度
     */
    public final static void pressImage(String watermarkImg, String targetImg, int x, int y, float alpha) {
        try {
            File img = new File(targetImg);
            Image src = ImageIO.read(img);
            int widthT = src.getWidth(null);
            int heightT = src.getHeight(null);
            BufferedImage image = new BufferedImage(widthT, heightT, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = image.createGraphics();
            g.drawImage(src, 0, 0, widthT, heightT, null);
            // 水印文件
            Image srcW = ImageIO.read(new File(watermarkImg));
            int widthW = srcW.getWidth(null);
            int heightW = srcW.getHeight(null);
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
            int posWidth = x > (widthT - widthW) ? widthT - widthW : x;
            int posHeight = y > (heightT - heightW) ? heightT - heightW : y;
            g.drawImage(srcW, posWidth, posHeight, widthW, heightW, null);
            // 水印文件结束
            g.dispose();
            ImageIO.write(image, "jpg", img);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 文字水印
     *
     * @param pressText 水印文字
     * @param targetImg 目标图片
     * @param fontName  字体名称
     * @param fontStyle 字体样式
     * @param color     字体颜色
     * @param fontSize  字体大小
     * @param x         修正值
     * @param y         修正值
     * @param alpha     透明度
     */
    public static void pressText(String pressText, String targetImg, String fontName,
                                 int fontStyle, Color color, int fontSize, int x, int y, float alpha) {
        try {
            File img = new File(targetImg);
            Image src = ImageIO.read(img);
            int width = src.getWidth(null);
            int height = src.getHeight(null);
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = image.createGraphics();
            g.drawImage(src, 0, 0, width, height, null);
            g.setColor(color);
            g.setFont(new Font(fontName, fontStyle, fontSize));
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
            g.drawString(pressText, (width - (getLength(pressText) * fontSize)) / 2 + x,
                    (height - fontSize) / 2 + y);
            g.dispose();
            ImageIO.write(image, "jpg", img);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 缩放
     *
     * @param filePath 图片路径
     * @param height   高度
     * @param width    宽度
     * @param bb       比例不对时是否需要补白
     */
    public static void resize(String filePath, int height, int width, boolean bb) {
        try {
            double ratio = 0.0; // 缩放比例
            File f = new File(filePath);
            if (!f.exists()) {
                // 当文件不存在时,返回
                return;
            }
            BufferedImage bi = ImageIO.read(f);
            if (bi == null) {
                return;
            }
            Image itemp = bi.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH);
            // 计算比例
            if ((bi.getHeight() > height) || (bi.getWidth() > width)) {
                if (bi.getHeight() > bi.getWidth()) {
                    ratio = (new Integer(height)).doubleValue() / bi.getHeight();
                } else {
                    ratio = (new Integer(width)).doubleValue() / bi.getWidth();
                }
                AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(
                        ratio, ratio), null);
                itemp = op.filter(bi, null);
            }
            if (bb) {
                BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                Graphics2D g = image.createGraphics();
                g.setColor(Color.white);
                g.fillRect(0, 0, width, height);
                if (width == itemp.getWidth(null)) {
                    g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2,
                            itemp.getWidth(null), itemp.getHeight(null), Color.white, null);
                } else {
                    g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0, itemp.getWidth(null),
                            itemp.getHeight(null), Color.white, null);
                }
                g.dispose();
                itemp = image;
            }
            ImageIO.write((BufferedImage) itemp, "jpg", f);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 裁剪图片
     *
     * @param filePath 文件路径
     * @param x        裁剪X坐标
     * @param y        裁剪Y坐标
     * @param height   裁剪高
     * @param width    裁剪宽
     * @return
     * @throws Exception
     */
    public static String cut(String filePath, int x, int y, int height, int width) throws Exception {
        if (!StrUtil.isNotBlank(filePath)) {
            throw new Exception("图片不存在!");
        }
        String newPath = "";
        FileInputStream is = null;
        ImageInputStream iis = null;
        try {
            // 分解文件后缀
            int splitIndex = filePath.lastIndexOf(".");
            String fileFullPath = filePath.substring(0, splitIndex);
            String fileSuffix = filePath.substring(splitIndex + 1);
            // 读取图片文件
            is = new FileInputStream(filePath);

            /*
             * 返回包含所有当前已注册 ImageReader 的 Iterator，这些 ImageReader
             * 声称能够解码指定格式。 参数：formatName - 包含非正式格式名称 .
             *（例如 "jpeg" 或 "tiff"）等 。
             */

            Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName(fileSuffix);
            ImageReader reader = null;
            if (it.hasNext()) {
                reader = it.next();
            } else {
                throw new Exception("图片类型不支持!");
            }
            // 获取图片流
            iis = ImageIO.createImageInputStream(is);

            /*
             * <p>iis:读取源.true:只向前搜索 </p>.将它标记为 ‘只向前搜索’。
             * 此设置意味着包含在输入源中的图像将只按顺序读取，可能允许 reader
             *  避免缓存包含与以前已经读取的图像关联的数据的那些输入部分。
             */
            reader.setInput(iis, true);

            /*
             * <p>描述如何对流进行解码的类<p>.用于指定如何在输入时从 Java Image I/O
             * 框架的上下文中的流转换一幅图像或一组图像。用于特定图像格式的插件
             * 将从其 ImageReader 实现的 getDefaultReadParam 方法中返回
             * ImageReadParam 的实例。
             */
            ImageReadParam param = reader.getDefaultReadParam();

            /*
             * 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域，通过 Rectangle 对象
             * 的左上顶点的坐标（x，y）、宽度和高度可以定义这个区域。
             */
            Rectangle rect = new Rectangle(x, y, width, height);

            // 提供一个 BufferedImage，将其用作解码像素数据的目标。
            param.setSourceRegion(rect);

            /*
             * 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象，并将
             * 它作为一个完整的 BufferedImage 返回。
             */
            BufferedImage bi = reader.read(0, param);

            // 保存新图片
            newPath = fileFullPath.concat("_cut.").concat(fileSuffix);
            File newFile = new File(newPath);
            if (newFile.createNewFile()) {
                ImageIO.write(bi, fileSuffix, newFile);
            }
        } finally {
            if (is != null) {
                is.close();
            }
            if (iis != null) {
                iis.close();
            }
        }
        return newPath;
    }

    /**
     * 生成缩略图
     *
     * @param targetFile 目标文件，如果是目录，为目录下所有文件创建缩略图
     * @param width      缩略图宽度
     * @param height     缩略图高度
     */
    public static void generateThumbnail(File targetFile, int width, int height) {
        if (targetFile.exists()) {
            if (targetFile.isDirectory()) {
                // 文件夹
                File[] listFiles = targetFile.listFiles();
                for (File subFile : listFiles) {
                    generateThumbnail(subFile, width, height);
                }
            } else {
                String type = FileTypeUtil.getType(targetFile);
                List<String> imgTypeNames = Lists.newArrayList("jpg", "jpeg", "png", "gif");
                if (!imgTypeNames.contains(type.toLowerCase())) {
                    // 非图片
                    return;
                }
                // 复制图片
                String fileName = FileUtil.getName(targetFile);
                if (StrUtil.isNotBlank(fileName)) {
                    int splitIndex = fileName.lastIndexOf(".");
                    StrBuilder thumbnailNameBuilder = StrBuilder.create();
                    if (splitIndex != -1) {
                        thumbnailNameBuilder.append(fileName.substring(0, splitIndex)).append("_thumbnail").append(fileName.substring(splitIndex));
                    } else {
                        thumbnailNameBuilder.append(fileName).append("_thumbnail");
                    }
                    String thumbnailPath = targetFile.getParent().concat(File.separator).concat(thumbnailNameBuilder.toString());
                    IoUtil.copy(FileUtil.getInputStream(targetFile), FileUtil.getOutputStream(thumbnailPath));
                    // 修改图片大小
                    resize(thumbnailPath, height, width, true);
                }
            }
        }
    }

    public static int getLength(String text) {
        int length = 0;
        for (int i = 0; i < text.length(); i++) {
            if (new String(text.charAt(i) + "").getBytes().length > 1) {
                length += 2;
            } else {
                length += 1;
            }
        }
        return length / 2;
    }

    public static void main(String[] args) throws IOException {
        String path = "F:\\图片\\新建文件夹";
        //ImageUtil.generateThumbnail(FileUtil.file(path), 150, 150);
        pressImage("F:\\图片\\娜.png", "F:\\图片\\新建文件夹\\201611160935039_b.jpg", 2000, 5000, Float.valueOf("0.5"));
        //pressText("我是文字水印", "G:\\imgtest\\test1.jpg", "黑体", 36, Color.white,80, 0, 0, 0.3f);
        //resize("E:\\aa.jpg", 100, 100, true);
    }
}
